<template>
    <div class="service-spec-select">
        <div class="price">
            <span class="currency">￥</span>
            <span class="price-text">{{ priceText }}</span>
        </div>
        <ul class="spec-list">
            <li v-for="spec in specStateList" :key="spec.specId">
                <div class="spec-name">{{ spec.name }}</div>
                <ul class="option-list">
                    <li
                        v-for="option in spec.options"
                        :key="option.optionId"
                        :class="{
                            active: isOptionActive(spec, option),
                            disabled: !checkSelectableOption(spec, option),
                        }"
                        @click="selectSpec(spec, option, !checkSelectableOption(spec, option))"
                    >
                        {{ option.optionName }}
                    </li>
                </ul>
            </li>
        </ul>
        <div class="service-num">
            <div class="spec-name">{{ t('serviceList.quantity') }}</div>
            <ElInputNumber v-model="serviceNum" :min="serviceNumRange[0]" :max="serviceNumRange[1]" size="small" />
        </div>
        <button
            :class="{ active: Boolean(selectedSku) }"
            class="purchase-btn"
            :disabled="!selectedSku"
            @click="confirmOrder"
        >
            {{ t('serviceList.buyNow') }}
        </button>
        <!-- <ServicePurchaseConfirm :visible="modalVisible" :order="order" /> -->
    </div>
</template>

<script lang="ts" setup>
import { computed, Ref, ref, watch, PropType, watchEffect, onMounted, nextTick, onUpdated } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { Spec, SpecOption, Sku, SkuSelection } from '@/types/service.d';
import { t } from '@/i18n';
// import ServicePurchaseConfirm from './ServicePurchaseConfirm.vue';

interface ActiveSpec extends Spec {
    activeOptionId: number | undefined;
}

const props = defineProps({
    specs: {
        type: Array as PropType<Array<Spec>>,
        default: () => [],
    },
    skus: {
        type: Array as PropType<Array<Sku>>,
        default: () => [],
    },
});

const router = useRouter();
const route = useRoute();
const priceText = ref('0');
const specStateList = ref([] as Array<ActiveSpec>);
const serviceNum: Ref<number> = ref(0);
const serviceNumRange = ref([1, 9999] as [number, number]);
const modalVisible = ref(false);
const order = ref({} as { [x: string]: any });
const id = ref('');
const locationSpecs: Ref<any> = ref([]);

onMounted(() => {
    if (route.query.serviceNum) {
        serviceNum.value = Number(route.query.serviceNum);
    }
    if (route.query.spec) {
        locationSpecs.value = route.query.spec;
    }
});

watch(locationSpecs, () => {
    setTimeout(() => {
        specStateList.value = props.specs.map((spec) => {
            const { options } = spec;
            let activeId;
            const option = options.find((opt) => locationSpecs.value.includes(opt.optionName));
            if (option) {
                activeId = option.optionId;
            }
            return {
                ...spec,
                activeOptionId: activeId,
                // options: JSON.parse(JSON.stringify(spec.options)),
            };
        });
    }, 300);
});

if (typeof route.params.id !== 'string') {
    const [value] = route.params.id;
    id.value = value;
} else {
    id.value = route.params.id;
}

const isOptionActive = computed(
    () => (spec: ActiveSpec, option: SpecOption) => spec.activeOptionId === option.optionId,
);

// 用于维护规格状态的新新列表
const selectedOptionList = computed(() =>
    specStateList.value.map(({ activeOptionId }) => activeOptionId).filter((e) => e),
);

const checkSelectableOption = computed(() => (activeSpec: ActiveSpec, option: SpecOption) => {
    const matchedSkuSelections = getMatchedSkuSelections(specStateList.value, props.skus, activeSpec, option);
    return Boolean(matchedSkuSelections.length);
});

const selectedSku = computed(() => {
    const selectedOptionIdList = specStateList.value.map((spec) => spec.activeOptionId).filter((e) => e);
    if (selectedOptionIdList.length < specStateList.value.length) {
        return false;
    }

    const findSku = props.skus.find((sku) =>
        sku.selections.every(({ optionId }) => selectedOptionIdList.includes(optionId)),
    );

    if (!findSku) {
        return false;
    }

    priceText.value = String(findSku.price * serviceNum.value);

    return findSku;
});

// 当前选中的项
const selectItem = computed(() => {
    const result: string[] = [];
    specStateList.value.forEach((item) => {
        const { activeOptionId, options } = item;
        const optionName = options.find((opt) => opt.optionId === activeOptionId)?.optionName;
        if (optionName) {
            result.push(optionName);
        }
    });
    return result;
});

// 监听 specs 变化更改 specStateList
watch(
    () => props.specs,
    () => {
        specStateList.value = props.specs.map(
            (spec) => ({
                ...spec,
                activeOptionId: undefined,
                options: JSON.parse(JSON.stringify(spec.options)),
            }),
            {
                immediate: true,
            },
        );
    },
);

watch(serviceNum, () => {
    const price = priceText.value;
    if (price.indexOf('-') > -1) {
        const arr: number[] = price.split('-').map((it) => parseInt(it, 10));
        priceText.value = `${arr[0] * serviceNum.value}-${arr[1] * serviceNum.value}`;
        return;
    }
    priceText.value = String(Number(priceText.value) * serviceNum.value);
});

watchEffect(() => {
    priceText.value = getPriceRangeText(props.skus);
});

/**
 * 规格选择处理函数
 * @param spec 当前规格
 * @param option 当前选项
 * @param disabled 是否可选
 */
function selectSpec(spec: Spec, option: SpecOption, disabled: Boolean) {
    if (disabled) {
        return;
    }

    const activeSelection = specStateList.value.find(({ specId }) => specId === spec.specId);
    if (activeSelection) {
        if (activeSelection.activeOptionId === option.optionId) {
            activeSelection.activeOptionId = undefined;
        } else {
            activeSelection.activeOptionId = option.optionId;
        }
    }
}

/**
 * 检测当前项是否可选
 * @param activeSpecs 所有规格
 * @param skus 所有价格配置
 * @param currentActiveSpec 当前规格
 * @param currentOption 当前选项
 */
function getMatchedSkuSelections(
    activeSpecs: Array<ActiveSpec>,
    skus: Array<Sku>,
    currentActiveSpec: ActiveSpec,
    currentOption: SpecOption,
) {
    const conditionSpecs = activeSpecs.filter((activeSpec) => activeSpec.specId !== currentActiveSpec.specId);

    // 基于当前选择筛选后的价格列表
    const matchedSku = skus.filter((sku) => checkActiveSpecSkuMatch(conditionSpecs, sku.selections));

    // 基于当前选项再次筛选后的价格列表
    const currentMatchSku = matchedSku.filter(({ selections }) =>
        selections.some(({ optionId }) => optionId === currentOption.optionId),
    );

    return currentMatchSku;
}

/**
 * 检查当前条件规格，是否与价格配置匹配
 * @param conditionSpecs 当前条件规格列表
 * @param filterSelections 当前价格配置列表
 */
function checkActiveSpecSkuMatch(conditionSpecs: Array<ActiveSpec>, filterSelections: Array<SkuSelection>) {
    return conditionSpecs.every((spec) =>
        filterSelections.some(
            (selection) =>
                spec.name === selection.specName &&
                (!spec.activeOptionId || selection.optionId === spec.activeOptionId),
        ),
    );
}

/**
 * 价格配置
 * @param skus 价格配置列表
 */
function getPriceRangeText(skus: Array<Sku>) {
    let priceList = skus.map(({ price }) => price);
    priceList = priceList.length ? priceList : [0];
    const priceRange = Array.from(new Set([Math.min(...priceList), Math.max(...priceList)]));
    return priceRange.join('-');
}

/**
 * 确认订单
 */
function confirmOrder() {
    const skuId = selectedSku.value.skuId;
    const userId = id.value;
    router.push({
        name: '/home/service-list/service-info',
        query: {
            skuId: skuId,
            userId: userId,
            priceText: priceText.value,
            serviceNum: serviceNum.value,
            spec: selectItem.value,
        },
    });
}
</script>

<style scoped>
.price {
    color: var(--red-color);
}

.currency {
    font-size: 24px;
}

.price-text {
    font-size: 32px;
}

.price {
    margin-bottom: 50px;
}

.spec-list > li:nth-last-child(n + 1) {
    margin-bottom: 32px;
}

.spec-name {
    font-size: var(--font-size-small);
    margin-bottom: 8px;
}

.option-list {
    display: flex;
    gap: 5px 16px;
    flex-wrap: wrap;
    flex: 0;
}

.option-list > li {
    height: 28px;
    line-height: 26px;
    max-width: 100%;
    border-radius: var(--border-radius);
    border: 1px solid var(--border-color-transparent);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 0 15px;
    font-size: var(--font-size-small);
    cursor: pointer;
}
.option-list > li.active {
    border-color: var(--primary-color);
    background-color: var(--section-color);
    color: var(--font-color-link);
}

.option-list > li.disabled {
    color: var(--font-color-dim);
    border-color: transparent;
    background-color: var(--background-slight-transparent);
    cursor: not-allowed;
}

.service-num {
    margin-bottom: 22px;
}

.purchase-btn {
    width: 130px;
    height: 34px;
    background-color: var(--background-gray);
    border-radius: var(--border-radius);
    border: none;
    color: var(--font-color-reverse);
    cursor: default;
}
.purchase-btn.active {
    background-color: var(--primary-color);
    cursor: pointer;
}
</style>
